#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2023/11/6 23:51
# @Author  : huidong.bai
# @File    : CommandHandler.py
# @Software: PyCharm
# @Mail    : MasterBai2018@outlook.com
import pdb
from src.core.Routine.TSASession import TSASession
from src.core.Assertion import AssertionFactory
from src.core.Routine.ClientSession import ClientSession
from threading import Lock
import time

class CommandHandler:
    def __init__(self, tsa_session, sre_session, voi_session, set_session, oms_session):
        self.tsa_session: TSASession = tsa_session
        self.sre_session: ClientSession = sre_session
        self.voi_session: ClientSession = voi_session
        self.set_session: ClientSession = set_session
        self.oms_session: ClientSession = oms_session
        self.processing = False
        self.processing_time = -1

        self.handlers = {
            "SYS": {
                "SLEEP": self.sys_sleep,
                "CMD": self.sys_cmd,
                "EXPECT": self.expect_function,
            },
            "TSA": {
                "DATA": self.tsa_data,
                "CREATE": self.tsa_create,
                "START": self.tsa_start,
                "STOP": self.tsa_stop,
                "CANCEL": self.tsa_cancel,
                "PARAMETER": self.tsa_parameter,
                "VRSET": self.tsa_vrset,
                "FREE": self.tsa_free,
                "WORKMODE": self.tsa_workmode,
                "EVENT": self.tsa_event
            },
            "SRE": {
                "CREATE": self.sre_create,
                "STARTENROLL": self.sre_startenroll,
                "STOPENROLL": self.sre_stopenroll
            },
            "VOI": {
                "CREATE": self.voi_create,
                "OPEN": self.voi_open,
                "CLOSE": self.voi_close
            },
            "SET": {
                "CREATE": self.set_create,
                "VRSET": self.set_vrset,
                "WAKEUPLIST": self.set_wakeuplist
            },
            "OMS": {
                "CREATE": self.oms_create,
                "EVENT": self.oms_event
            }
        }
    def set_asserter(self, asserter: AssertionFactory):
        self.asserter = asserter

    def set_config(self, decoder):
        self.config = decoder
    
    def set_index(self, index):
        self.index = index
    
    def set_lock(self, lock: Lock):
        self.assert_lock = lock

    def execute_command(self, client, timestamp, cmder, param, collect_data):
        if client in self.handlers and cmder in self.handlers[client]:
            if client == "SYS" and cmder == "EXPECT":
                self.handlers[client][cmder](param, collect_data)
            else:
                self.handlers[client][cmder](param)

    def async_task(self, client, timestamp, cmder, param, collect_data):
        while True:
            if timestamp == self.processing_time:
                if client == "SYS" and cmder == "EXPECT":
                    self.handlers[client][cmder](param, collect_data)
                    break
                else:
                    self.handlers[client][cmder](param)
                    break
            elif not self.processing:
                break
            time.sleep(0.01)

    def expect_function(self, param: list, collect_data: list):
        with self.assert_lock:
            expect_type, assert_items = param.pop(0), param[0]
            self.asserter.routine_assert_results(collect_data, expect_type, assert_items)

    def sys_sleep(self, param):
        import time
        time.sleep(float(param[0]))

    def sys_cmd(self, param):
        import os
        os.system(" ".join(param))

    def time_callback(self, process_time):
            self.processing_time = process_time

    def tsa_data(self, param):
        self.processing = True
        audio, start, end, mic, ref = param
        frame_size = (int(mic) + int(ref)) * 320
        self.tsa_session.process_data(audio, frame_size, int(start), int(end), self.time_callback)
        self.processing = False

    def tsa_create(self, param):
        lang, appid = param
        return self.tsa_session.create(self.config, lang, appid)

    def tsa_start(self, param):
        channel_num = int(param[0])
        return self.tsa_session.start(index=self.index, channel=channel_num)

    def tsa_stop(self, param):
        return self.tsa_session.stop()

    def tsa_cancel(self, param):
        return self.tsa_session.cancel()

    def tsa_event(self, param):
        event = param[0]
        return self.tsa_session.set_event(eval(event))

    def tsa_free(self, param):
        return self.tsa_session.free()

    def tsa_workmode(self, param):
        work_mode = param[0]
        return self.tsa_session.set_work_mode(work_mode)

    def tsa_parameter(self, param):
        _type, _param = param
        return self.tsa_session.set_engine_param(_type, _param)

    def tsa_vrset(self, param):
        _type, _param = param
        return self.tsa_session.set_vr_config(_type, _param)

    def sre_create(self, param):
        lang, appid = param
        return self.sre_session.create(self.config, lang, appid)

    def sre_startenroll(self, param):
        user_id, text, index, channel_id = param
        return self.sre_session.start_speaker_enroll(self, user_id, text, index, channel_id)

    def sre_stopenroll(self, param):
        return self.sre_session.end_speaker_enroll()

    def voi_create(self, param):
        lang, appid = param
        return self.voi_session.create(self.config, lang, appid)

    def voi_open(self, param):
        json_data = param[0]
        return self.voi_session.open_voice_input(self, json_data)

    def voi_close(self, param):
        return self.voi_session.close_voice_input()

    def set_create(self, param):
        lang, appid = param
        return self.set_session.create(self.config, lang, appid)

    def set_vrset(self, param):
        _type, _param = param
        return self.set_session.set_vr_config(_type, _param)

    def set_wakeuplist(self, param):
        return self.set_session.get_wakeup_word_list()

    def oms_create(self, param):
        lang, appid = param
        return self.oms_session.create(self.config, lang, appid)

    def oms_event(self, param):
        event = param[0]
        return self.oms_session.set_event(eval(event))
